package lib.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import lib.base.http.Req
import lib.base.note.PageStatusNote

/**
 *  author: luoXiong
 *  e-mail: 382060748@qq.com
 *  date: 2021/9/2 13:07
 *  version: 1.0
 *  desc:
 */
open class BaseViewModel : ViewModel() {
    private val _defUI: UIChange = UIChange()

    /**
     * 所有网络请求都在 viewModelScope 域中启动，当页面销毁时会自动
     * 调用ViewModel的  #onCleared 方法取消所有协程
     */
    fun launch(block: suspend CoroutineScope.() -> Unit) = viewModelScope.launch(Dispatchers.Default) {
        try {
            block()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    fun launchFromMain(req: Req<Any>, block: suspend CoroutineScope.() -> Unit) {
        showLoadingDialog(req)
        viewModelScope.launch(Dispatchers.Main) {
            try {
                block()
                onReqComplete(req)
            } catch (e: Throwable) {
                e.printStackTrace()
                onReqComplete(req, true)
                // 统一处理接口错误
                // handleNetReqError(e, req)
                req.onErrorBefore(e)
            } finally {
                req.onComplete()
            }
        }
    }

    private fun showLoadingDialog(req: Req<*>? = null) {
        if (req != null && req.isShowLoadingDialog()) {
            val pageStatus = req.getShowPageStatus()
            when (pageStatus) {
                PageStatusNote.def_loading -> {
                    // if (req.isShowLoadingDialog()) {
                    _defUI.showDialog.value = req.getDialogLoadingText()
                    // }
                }
                else -> {
                    _defUI.pageStatusEvent.value = pageStatus
                }
            }
        }
    }

    fun showEmptyStatus(showEmpty: Boolean) {
        if (showEmpty) {
            _defUI.pageStatusEvent.value = PageStatusNote.show_page_empty
        } else {
            _defUI.pageStatusEvent.value = PageStatusNote.hide_status_layout
        }
    }

    fun dismissLoadingDialog() {
        _defUI.pageStatusEvent.value = PageStatusNote.dismiss_loading_dialog
    }

//    fun showErrorBySendEvent(){
//        _defUI.pageStatusEvent.value = PageStatusNote.show_page_error
//    }

    private fun onReqComplete(req: Req<*>? = null, isError: Boolean = true) {
        if (req != null) {
            val pageStatus = req.getShowPageStatus()
//            Timber.d("onReqComplete()..888...pageStatus=$pageStatus  isShow=${req.isShowLoadingDialog()}")
            when (pageStatus) {
                PageStatusNote.def_loading -> {
                    if (req.isShowLoadingDialog()) {
                        _defUI.pageStatusEvent.value = PageStatusNote.dismiss_loading_dialog
                    }
                }
                else -> {
                    _defUI.pageStatusEvent.value = PageStatusNote.hide_status_layout
                }
            }
        }
    }

    fun <T> sendRequest(req: Req<T>) {
        showLoadingDialog(req)
        viewModelScope.launch(Dispatchers.Main) {
            try {
                val resultVo = req.getApi().invoke()
                //val resultVo = req.getApi().invoke()
                // 让loading消失
                onReqComplete(req)
                // 回到主线程
                req.onSucceed(resultVo)
            } catch (e: Throwable) {
                e.printStackTrace()
                onReqComplete(req, true)
                // 全局处理后端接口异常
                // MviConfig.mviAction.handleNetReqError(e, req)
                req.onErrorBefore(e)
            } finally {
                req.onComplete()
            }
        }
    }


    open fun getUC(): UIChange {
        return _defUI
    }

    // 发送外部请求,比如:七牛,海康萤石token接口,高德地址.
//    fun <T> sendOutReq(outReq: OutNetReqB<T>) {
//        val req = outReq.getReqCb()
//        showLoadingDialog(req)
//        viewModelScope.launch(Dispatchers.Main) {
//            try {
//                val resultVo = withContext(Dispatchers.IO) {
//                    outReq.getReqResult()
//                }
//                onReqComplete(req)
//                // 回到主线程
//                req.onSucceed(resultVo)
//            } catch (e: Throwable) {
//                e.printStackTrace()
//                onReqComplete(req)
//                MviConfig.mviAction.handleNetReqError(e, req)
//                req.onErrorBefore(e)
//            } finally {
//                req.onComplete()
//            }
//        }
//    }


    /**
     * 异常统一处理
     */
    private suspend fun <T> handleException(
        request: suspend CoroutineScope.() -> T,
        success: suspend CoroutineScope.(T) -> Unit,
        error: suspend CoroutineScope.(Throwable) -> Unit, // ResponseThrowable
        complete: suspend CoroutineScope.() -> Unit
    ) {
        coroutineScope {
            try {
                success(request())
            } catch (e: Throwable) {
                e.printStackTrace()
                // error(NetReqErrorHandle.handleException(e))
                error(e)
            } finally {
                complete()
            }
        }
    }

    /**
     * UI事件
     */
    inner class UIChange {
        val showDialog by lazy { SingleLiveEvent<String>() }

        @PageStatusNote
        val pageStatusEvent by lazy { SingleLiveEvent<Int>() }
    }
}